package com.mayuanfei.springaop.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

/**
 * 添加方法的切面实现类
 *
 * @author 老马
 * @date 2023-03-01 13:19
 */
public class AddAspectXml {

    /**
     * 前置通知 切点方法执行前执行的功能
     *
     * @param joinPoint 切点对象,可以获取方法执行参数
     */
    public void methodBefore(JoinPoint joinPoint) {
        System.out.println("前置通知执行:" + joinPoint.getTarget().getClass());
    }

    /**
     * 后置通知 方法执行后要增强的功能
     *
     * @param joinPoint 切点对象
     */
    public void methodAfter(JoinPoint joinPoint) {
        System.out.println("后置通知执行:" + joinPoint.getTarget().getClass());
    }

    /**
     * 返回通知:切点方法正常运行结束后增强的功能
     * 如果方法运行过程中出现异常,则该功能不运行
     *
     * @param joinPoint 切点对象
     * @param res res接收方法返回值,需要用returning指定返回值名称
     */
    public void methodAfterReturning(JoinPoint joinPoint,Object res){
        System.out.println("返回通知执行:" + joinPoint.getTarget().getClass() + ", 返回结果:"+res);
    }

    /**
     * 异常通知:切点方法出现异常时运行的增强功能
     * 如果方法运行没有出现异常,则该功能不运行
     *
     * @param joinPoint 切点对象
     * @param e 接收异常对象 需要通过throwing指定异常名称
     */
    public void methodAfterThrowing(JoinPoint joinPoint, Exception e){
        System.out.println("异常通知执行:" + joinPoint.getTarget().getClass() + ", 异常信息:"+e.getMessage());
    }

    /**
     * 环绕通知 在切点方法之前和之后都进行功能的增强
     * 方法列表可以通过ProceedingJoinPoint获取执行的切点
     * 通过proceedingJoinPoint.proceed()方法控制切点方法的执行位置
     * 在环绕通知的最后需要将切点方法的返回值继续向上返回,否则切点方法在执行时接收不到返回值
     *
     * @param proceedingJoinPoint 执行的切点
     * @return 原方法返回的结果
     * @throws Throwable 异常
     */
    public Object methodAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕通知方法前执行:" + proceedingJoinPoint.getTarget().getClass());
        Object proceed = proceedingJoinPoint.proceed();
        System.out.println("环绕通知方法后执行:" + proceedingJoinPoint.getTarget().getClass());
        return proceed;
    }


}